package com.vict.util;

import java.math.BigInteger;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Util {
    static final char hexDigitsLower[] = { '0', '1', '2', '3', '4', '5', '6', '7','8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    public static final String md5PrxVersion = "md5L1"; // 第一版 没有cid参数
    public static final String md5Pattern = "md5L1[0-9a-f]{32}";
    public static final String md5PrxVersion2 = "md5L2"; // 第二版 有cid参与 "cid_.+_key_.+";
    public static final String md5Pattern2 = "md5L2[0-9a-f]{32}";

    public static String md5nagetive(String str, Charset charset){
        return MD5LowerByCharset(str, charset);
    }

    public static String md5Utf8(String str){
        if(str == null || str.trim().equals("")){
            return null;
        }

        if(str != null && !str.trim().equals("") && str.startsWith(md5PrxVersion) && str.length() == 37 && str.matches(md5Pattern)){
            return str; // 已经md5计算 直接返回
        }

        String s = MD5LowerByCharset(str, Charset.forName("UTF-8"));

        return md5PrxVersion + s;
    }

    public static String md5(String str){
        if(str == null || str.trim().equals("")){
            return null;
        }

        if(str != null && !str.trim().equals("") && str.startsWith(md5PrxVersion) && str.length() == 37 && str.matches(md5Pattern)){
            return str; // 已经md5计算 直接返回
        }

        String s = MD5Lower(str);

        return md5PrxVersion + s;
    }

    public static String md5Force(String str){
        if(str == null || str.trim().equals("")){
            return null;
        }
        String s = MD5Lower(str);
        return md5PrxVersion + s;
    }

    public static String md5(String cid, String str){
        if(cid == null || cid.trim().equals("")){ // 没有cid降级为md51版本
            return md5(str);
        }
        if(str == null || str.trim().equals("")){ // 没有编码值 直接返回null
            return null;
        }
        if(str != null && !str.trim().equals("") && str.startsWith(md5PrxVersion2) && str.length() == 37 && str.matches(md5Pattern2)){
            return str; // 已经md5计算 直接返回
        }
        String reg = "cid_.+_key_.+";
        if(str.matches(reg)){ // 已经拼接 无需再次拼接
            String md5 = MD5Lower(str);
            return md5PrxVersion2 + md5;
        }else{ // 没有编码过 编码后再md5计算
            String md5 = MD5Lower("cid_" + cid + "_key_" + str);
            return md5PrxVersion2 + md5;
        }
    }

    public static String md5Force(String cid, String str){
        if(cid == null || cid.trim().equals("")){ // 没有cid降级为md51版本
            return md5(str);
        }
        if(str == null || str.trim().equals("")){ // 没有编码值 直接返回null
            return null;
        }
        String md5 = MD5Lower("cid_" + cid + "_key_" + str);
        return md5PrxVersion2 + md5;
    }

    public static boolean isMatchMd5(String md5Str, String version){
        if(md5PrxVersion.equals(version)){
            if(md5Str != null && !md5Str.trim().equals("") && md5Str.startsWith(md5PrxVersion) && md5Str.length() == 37 && md5Str.matches(md5Pattern)){
                return true; // 已经md5计算
            }else{
                return false;
            }
        }else if(md5PrxVersion2.equals(version)){
            if(md5Str != null && !md5Str.trim().equals("") && md5Str.startsWith(md5PrxVersion2) && md5Str.length() == 37 && md5Str.matches(md5Pattern2)){
                return true; // 已经md5计算
            }else{
                return false;
            }
        }
        return false;
    }

    /**
     * 对字符串 MD5 无盐值加密
     * @param plainText 传入要加密的字符串
     * @return MD5加密后生成32位(小写字母+数字)字符串
     */
    private static String MD5Lower(String plainText) {
        try {
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            md.update(plainText.getBytes());
            return new BigInteger(1,  md.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return plainText;
        }
    }

    /**
     * 对字符串 MD5 无盐值加密
     * @param plainText 传入要加密的字符串
     * @return MD5加密后生成32位(小写字母+数字)字符串
     */
    private static String MD5LowerByCharset(String plainText, Charset charset) {
        try {
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            md.update(plainText.getBytes(charset));
            return new BigInteger(1,  md.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return plainText;
        }
    }
}
